package com.yanqu.road.server.manager.zhaoshang;

import com.yanqu.road.dao.impl.zhaoshang.ZsProjectAdditionDataDaoImpl;
import com.yanqu.road.entity.config.zhaoshang.ZsProjectInfo;
import com.yanqu.road.entity.enums.eRedHotNotifyType;
import com.yanqu.road.entity.interfaces.HideVipAddressMark;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.servercenter.CrossServerGroup;
import com.yanqu.road.entity.zhaoshang.*;
import com.yanqu.road.entity.zhaoshang.enums.*;
import com.yanqu.road.entity.zhaoshang.result.ZsProjectOpenResult;
import com.yanqu.road.entity.zhaoshang.result.ZsProjectSeatRobResult;
import com.yanqu.road.entity.zhaoshang.warp.ZsAdditionInfos;
import com.yanqu.road.logic.bussiness.zhaoshang.ZhaoShangBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.ZhaoShangPb;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.pb.zhaoshang.ZhaoShangProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.zhaoshang.sort.ZsProjectSortEntity;
import com.yanqu.road.server.manager.zhaoshang.sort.ZsSortOrderByAddTime;
import com.yanqu.road.server.manager.zhaoshang.sort.ZsSortOrderByProfit;
import com.yanqu.road.server.manger.CrossServerGroupMgr;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class ZsMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(ZsMgr.class.getName());

    //serverId,projectId
    private static Map<Long, Map<Long, ZsProject>>  zsAllProjectMap;           //项目集
    //projectId
    private static Map<Long, List<ZsProjectNotice>> zsAllProjectNoticeMap;     //项目公告

    //projectId
    private static Map<Long, List<ZsWarReport>>  zsAllWarReportMap;            //战报（跨服冗余一份）

    //userId
    private static Map<Long, List<ZsProjectReward>> zsAllRewardMap;            //奖励

    private static AtomicLong globalProjectId;                                 //全局项目id

    private static Map<Long, ZsUserCoolDown> zsUserCoolDownMap;                //玩家冷却时间

    private static int keepDataDays = 2;                                       //加载数据保留时间

    @Override
    public boolean reloadData() throws Exception {
        //加载过去两天的项目
        int beginTime = (int)((System.currentTimeMillis() - DateHelper.DAY_MILLIONS * keepDataDays) / 1000);
        zsAllProjectMap = ZhaoShangBussiness.getZsAllProjectMap(beginTime);

        Map<Long, ZsProjectAdditionData> zsAdditionMap = new ZsProjectAdditionDataDaoImpl().getZsProjectAdditionData(beginTime);

        for(long serverId : zsAllProjectMap.keySet()) {
            Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(serverId);
            for (Map.Entry<Long, ZsProject> dataEntry : zsProjectMap.entrySet()) {
                ZsProjectAdditionData additionData = zsAdditionMap.get(dataEntry.getKey());
                if(additionData != null){
                    dataEntry.getValue().setAdditionData(additionData);
                }
                setExpectProfit(dataEntry.getValue());
            }
        }

        zsAllProjectNoticeMap = ZhaoShangBussiness.getZsAllProjectNoticeMap(beginTime);
        zsAllWarReportMap = ZhaoShangBussiness.getCrossZsWarReportMap(beginTime);

        if(globalProjectId == null) {
            globalProjectId = new AtomicLong(ZhaoShangBussiness.getMaxProjectId());
        }

        zsUserCoolDownMap = ZhaoShangBussiness.getZsUserCoolDownMap();

        //加载过去20天奖励
        int endTime = (int)((System.currentTimeMillis() - DateHelper.DAY_MILLIONS * 20) / 1000);
        zsAllRewardMap = ZhaoShangBussiness.getZsAllRewardMap(endTime);
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        saveData();
        try {
            removeOutTimeData();
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
        return true;
    }

    public static void saveData(){
        for(long serverId : zsAllProjectMap.keySet()){
            Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(serverId);
            for(Map.Entry<Long, ZsProject> dataEntry : zsProjectMap.entrySet()){
                ZsProject zsProject = dataEntry.getValue();
                if(zsProject.getExpectProfit() == 0){
                    setExpectProfit(zsProject);
                }
                if(zsProject.isInsertOption()){
                    ZhaoShangBussiness.addZsProject(zsProject);
                }else if(zsProject.isUpdateOption()){
                    ZhaoShangBussiness.updateZsProject(zsProject);
                }
                ZsProjectAdditionData additionData = zsProject.getAdditionData();
                if(additionData != null){
                    if(additionData.isInsertOption()){
                        new ZsProjectAdditionDataDaoImpl().add(additionData);
                    }
                }
            }
        }

        //奖励
        for(Map.Entry<Long, List<ZsProjectReward>> entry : zsAllRewardMap.entrySet()){
            List<ZsProjectReward> rewardList = entry.getValue();
            int size = rewardList.size();
            for(int i = 0; i < size; i++){
                ZsProjectReward reward = rewardList.get(i);
                if (reward.isInsertOption()) {
                    ZhaoShangBussiness.addZsProjectReward(reward);
                } else if (reward.isUpdateOption()) {
                    ZhaoShangBussiness.updateZsProjectReward(reward);
                }
            }
        }

        for(Map.Entry<Long, List<ZsWarReport>> listEntry : zsAllWarReportMap.entrySet()){
            List<ZsWarReport> reportList = listEntry.getValue();
            int size = reportList.size();
            for(int i = 0; i < size; i++){
                ZsWarReport zsWarReport = reportList.get(i);
                if (zsWarReport.isInsertOption()) {
                    ZhaoShangBussiness.addCrossZsWarReport(zsWarReport);
                } else if (zsWarReport.isUpdateOption()) {
                    ZhaoShangBussiness.updateCrossZsWarReport(zsWarReport);
                }
            }
        }

        for(Map.Entry<Long, List<ZsProjectNotice>> listEntry : zsAllProjectNoticeMap.entrySet()){
            List<ZsProjectNotice> noticeList = listEntry.getValue();
            int size = noticeList.size();
            for(int i = 0; i < size; i++){
                ZsProjectNotice zsProjectNotice = noticeList.get(i);
                if (zsProjectNotice.isInsertOption()) {
                    ZhaoShangBussiness.addZsProjectNotice(zsProjectNotice);
                }
            }

        }

        for(long userId : zsUserCoolDownMap.keySet()){
            ZsUserCoolDown zsUserCoolDown = zsUserCoolDownMap.get(userId);
            if(zsUserCoolDown.isInsertOption()){
                ZhaoShangBussiness.addZsUserCoolDown(zsUserCoolDown);
            }else if(zsUserCoolDown.isUpdateOption()){
                ZhaoShangBussiness.updateZsUserCoolDown(zsUserCoolDown);
            }
        }

    }

    //获取区服项目
    public static Map<Long, ZsProject> getZsProjectMapByServerId(long serverId){
        return zsAllProjectMap.get(serverId);
    }

    //全局查找项目
    public static ZsProject getZsProjectById(long projectId){
        for(long serverId : zsAllProjectMap.keySet()){
            Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(serverId);
            if(zsProjectMap.containsKey(projectId)){
                return zsProjectMap.get(projectId);
            }
        }
        return null;
    }

    //全局查找项目
    public static ZsProject getZsProjectByServerIdAndId(long serverId, long projectId){
        if(zsAllProjectMap.containsKey(serverId)){
            return zsAllProjectMap.get(serverId).get(projectId);
        }
        return null;
    }

    //获取玩家立项的项目(根据userId别名)
    public static List<ZsProject> getUserOpenProjectByAliasId(long serverId, long userAliasId, int stateVal){
        List<ZsProject> list = new ArrayList<>();
        List<Long> groupServer = getGroupServer(serverId);
        for(long server : groupServer) {
            if (zsAllProjectMap.containsKey(server)) {
                Map<Long, ZsProject> serverProjectMap = zsAllProjectMap.get(server);
                ZsProject project;
                for (long key : serverProjectMap.keySet()) {
                    project = serverProjectMap.get(key);
                    if (project == null) {
                        continue;
                    }
                    int nowState = calZsProjectStateVal(project);
                    if (nowState == stateVal && project.getOpenUser().getUserAliasId() == userAliasId) {
                        list.add(project);
                    }
                }
            }
        }
        return list;
    }

    //获取玩家立项的项目
    public static List<ZsProject> getUserOpenProject(long serverId, long playId, int stateVal){
        List<ZsProject> list = new ArrayList<>();
        if(zsAllProjectMap.containsKey(serverId)) {
            Map<Long, ZsProject> serverProjectMap = zsAllProjectMap.get(serverId);
            ZsProject project;
            for (long key : serverProjectMap.keySet()) {
                project = serverProjectMap.get(key);
                if(project == null){
                    continue;
                }
                int nowState = calZsProjectStateVal(project);
                if (nowState == stateVal && project.getOpenUserId() == playId) {
                    list.add(project);
                }
            }
        }
        return list;
    }

    //获取玩家加入的项目(根据玩家别名-只查本分组区服)
    public static List<ZsProject> getUserJoinProjectByAliasId(long serverId, long userAliasId, int stateVal) {
        List<ZsProject> list = new ArrayList<>();
        List<Long> groupServer = getGroupServer(serverId);
        for(long server : groupServer) {
            if (zsAllProjectMap.containsKey(server)) {
                Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(server);
                for (long key : zsProjectMap.keySet()) {
                    ZsProject project = zsProjectMap.get(key);
                    if (project == null) {
                        continue;
                    }
                    int nowState = calZsProjectStateVal(project);
                    if (nowState == stateVal) {
                        for (int seatId : project.getSeatMap().keySet()) {
                            ZsProjectSeat seat = project.getSeatMap().get(seatId);
                            if (project.getSeatUserMap().get(seatId).getUserAliasId() == userAliasId) {
                                list.add(project);
                            }
                        }
                    }
                }
            }
        }
        return list;
    }

    //获取玩家加入的项目
    public static List<ZsProject> getUserJoinProject(long serverId, long playId, int stateVal) {
        List<ZsProject> list = new ArrayList<>();
        List<Long> serverList = getGroupServer(serverId);
        for(long sid : serverList) {
            if(zsAllProjectMap.containsKey(sid)) {
                Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(sid);
                for (long key : zsProjectMap.keySet()) {
                    ZsProject project = zsProjectMap.get(key);
                    if(project == null){
                        continue;
                    }
                    int nowState = calZsProjectStateVal(project);
                    if (nowState == stateVal) {
                        for (int seatId : project.getSeatMap().keySet()) {
                            ZsProjectSeat seat = project.getSeatMap().get(seatId);
                            if (seat.getUserId() == playId) {
                                list.add(project);
                            }
                        }
                    }
                }
            }
        }
        return list;
    }

    public static Map<Long, ZsUserCoolDown> getZsUserCoolDownMap() {
        return zsUserCoolDownMap;
    }

    private static List<ZsWarReport> getWarZsWarReport(long projectId){
        List<ZsWarReport> resultList = new ArrayList<>();
        if(zsAllWarReportMap.containsKey(projectId)){
            List<ZsWarReport> list = zsAllWarReportMap.get(projectId);
            if(list == null){
                return  resultList;
            }
            for(int i = 0; i < list.size(); i++){
                resultList.add(list.get(i));
            }
        }
        return resultList;
    }

    //获取公告
    public static List<ZsProjectNotice> getZsProjectNotice(long projectId) {
        List<ZsProjectNotice> resultList = new ArrayList<>();
        if (zsAllProjectNoticeMap.containsKey(projectId)){
            List<ZsProjectNotice> list = zsAllProjectNoticeMap.get(projectId);
            if(list == null){
                return  resultList;
            }
            for(int i = 0; i < list.size(); i++){
                resultList.add(list.get(i));
            }
        }
        return resultList;
    }

    //获取(最后一封防守战报)
    private static ZsWarReport findWinWarReport(long projectId, long userId, int seatId, long enemyUserId) {
        List<ZsWarReport> reportList = getWarZsWarReport(projectId);
        if(reportList.size() == 0){
            return null;
        }
        ZsWarReport last = null;
        for(ZsWarReport report : reportList){
            if(report.getUserId() == userId && report.getSeatId() == seatId && report.getEnemyUserId() == enemyUserId){
                last = report;
            }
        }
        return last;
    }

    //查列表
    public static void listProjects(long searchUserAliasId, long serverId, long playerId, int listSizeLimit, int templateId) {
        if(searchUserAliasId > 0){
            List<ZsProject> zsProjectList = getUserOpenProjectByAliasId(serverId, searchUserAliasId, eProjectStateType.InProgress.getIntValue());
            zsProjectList.addAll(getUserJoinProjectByAliasId(serverId, searchUserAliasId, eProjectStateType.InProgress.getIntValue()));
            //查本服玩家立项和参与的项目，按日期倒序
            ZsSortOrderByAddTime sort = new ZsSortOrderByAddTime();
            zsProjectList.sort(sort);
            //转换Message
            ZhaoShangProto.ZsProjectListRespMsg.Builder respMsg = ZhaoShangProto.ZsProjectListRespMsg.newBuilder();
            respMsg.setRet(0);
            respMsg.setSearchUserAliasId(searchUserAliasId);
            for(ZsProject entity : zsProjectList){
                ZhaoShangProto.ZsProjectInfoTemp.Builder temp = ZhaoShangPb.parseZsProjectInfoTemp(entity, false, playerId);
                if(!respMsg.hasSearchUser()) {
                    if(searchUserAliasId == entity.getOpenUser().getUserAliasId()){
                        respMsg.setSearchUser(PlayerBasePb.parsePlayerBaseTempMsg(entity.getOpenUser()));
                        respMsg.setSearchUserId(entity.getOpenUserId());
                    }else {
                        for (int seatId : entity.getSeatUserMap().keySet()) {
                            ZsProjectSeat zsProjectSeat = entity.getSeatMap().get(seatId);
                            if (entity.getSeatUserMap().get(seatId).getUserAliasId() == searchUserAliasId) {
                                respMsg.setSearchUser(PlayerBasePb.parsePlayerBaseTempMsg(entity.getSeatUserMap().get(seatId)));
                                respMsg.setSearchUserId(zsProjectSeat.getUserId());
                            }
                        }
                    }
                }
                temp.setCross(inGroup(entity.getServerId()));
                respMsg.addProjectList(temp);
            }
            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_ZS_PROJECT_SEARCH, respMsg));
        }else{
            //查所在分组的所有项目，按我立项、我参与、收益高至低
            List<Long> serverList = getGroupServer(serverId);
            LinkedList<ZsProjectSortEntity> pseudoList = new LinkedList<>();
            for(long sid : serverList){
                Map<Long, ZsProject> zsProjectMap = getZsProjectMapByServerId(sid);
                if(zsProjectMap == null){
                    continue;
                }
                for(long key : zsProjectMap.keySet()){
                    ZsProject zsProject = zsProjectMap.get(key);
                    int stateVal = calZsProjectStateVal(zsProject);
                    if(stateVal == eProjectStateType.End.getIntValue()){
                        continue;
                    }
                    //来自项目榜，需过滤
                    if(templateId > 0 && zsProject.getTemplateId() != templateId){
                        continue;
                    }
                    pseudoList.add(new ZsProjectSortEntity(key, sid));
                }
            }
            ZsSortOrderByProfit sort = new ZsSortOrderByProfit(playerId, serverId, templateId != -1);
            pseudoList.sort(sort);
            while(pseudoList.size() > listSizeLimit){
                pseudoList.removeLast();
            }
            //转换Message
            ZhaoShangProto.ZsProjectListRespMsg.Builder respMsg = ZhaoShangProto.ZsProjectListRespMsg.newBuilder();
            respMsg.setRet(0);
            respMsg.setSearchUserAliasId(searchUserAliasId);
            for(ZsProjectSortEntity entity : pseudoList){
                ZsProject zsProject = getZsProjectMapByServerId(entity.getServerId()).get(entity.getProjectId());
                ZhaoShangProto.ZsProjectInfoTemp.Builder temp = ZhaoShangPb.parseZsProjectInfoTemp(zsProject, false, playerId);
                temp.setCross(inGroup(entity.getServerId()));
                //来自项目榜，附带成员基本信息
                if(templateId != -1){
                    temp.setExpectProfit(zsProject.getExpectProfit());
                    for(int seatId : zsProject.getSeatUserMap().keySet()){
                        temp.addSeatInfo(ZhaoShangPb.parseZsProjectSeatSimpleInfo(seatId, zsProject.getSeatMap().get(seatId), zsProject.getSeatUserMap().get(seatId)));
                    }
                }
                respMsg.addProjectList(temp);
            }
            if(templateId >= 0){
                //项目榜
                MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_ZS_PROJECT_SIMPLE_LIST, respMsg));
            }else {
                //项目列表
                MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_ZS_PROJECT_LIST, respMsg));
            }
        }
    }

    //区服分组是否有变更（认定为变更的条件是：已占位的区服范围超出了项目立项区服当前所属的区服范围）
    private static boolean serverGroupChange(long serverId, Set<Long> seatServerSet) {
        List<Long> serverIdList = getGroupServer(serverId);
        for(long val : serverIdList){
            seatServerSet.remove(val);
        }
        if(seatServerSet.size() == 0){
            return false;
        }
        return true;
    }

    //获取所在组的区服列表(没有分组即独自成组)
    public static List<Long> getGroupServer(long serverId){
        List<Long> serverList = new ArrayList<>();
        CrossServerGroup serverGroup = CrossServerGroupMgr.getServerGroupByServerId(serverId);
        if(serverGroup == null || serverGroup.getCrossZsState() == 0){
            serverList.add(serverId);
        }else{
            serverList.addAll(serverGroup.getServerList());
        }
        return serverList;
    }

    //区服是否在分组中
    public static boolean inGroup(long serverId){
        return (int)serverId != getGroupId(serverId) && getGroupServer(serverId).size() > 1;
    }

    public static int getGroupId(long serverId) {
        CrossServerGroup serverGroup = CrossServerGroupMgr.getServerGroupByServerId(serverId);
        if(serverGroup != null && serverGroup.getCrossZsState() == 1){
            return serverGroup.getGroupId();
        }
        return (int)serverId;
    }

    //计算项目状态
    public static int calZsProjectStateVal(ZsProject zsProject){
        if(zsProject.getStateVal() == eProjectStateType.End.getIntValue()){
            return eProjectStateType.End.getIntValue();
        }
        int passMinute = (DateHelper.getCurrentSecond() - zsProject.getOpenTime()) / 60;
        if(passMinute >= zsProject.getDuration()){
            return  eProjectStateType.End.getIntValue();
        }
        return eProjectStateType.InProgress.getIntValue();
    }


    //-------------------------------

    /**
     * 新增项目
     * @param zsProject
     */
    public static void addZsProject(ZsProject zsProject){
        if(!zsAllProjectMap.containsKey(zsProject.getServerId())){
            synchronized (zsAllProjectMap){
                if(!zsAllProjectMap.containsKey(zsProject.getServerId())){
                    zsAllProjectMap.put(zsProject.getServerId(), new ConcurrentHashMap<>());
                }
            }
        }
        zsAllProjectMap.get(zsProject.getServerId()).put(zsProject.getProjectId(), zsProject);
    }

    //添加项目公告
    public static void addProjectNotice(long projectId, ZsProjectNotice notice) {
        if(zsAllProjectNoticeMap.get(projectId) == null){
            synchronized (zsAllProjectNoticeMap){
                if(zsAllProjectNoticeMap.get(projectId) == null){
                    zsAllProjectNoticeMap.put(projectId, new ArrayList<>());
                }
            }
        }
        List<ZsProjectNotice> list = zsAllProjectNoticeMap.get(projectId);
        if(list == null){
            return;
        }
        synchronized (list) {
            list.add(notice);
        }
    }

    //添加战报
    private static void addWarReport(long projectId, ZsWarReport report){
        if(!zsAllWarReportMap.containsKey(projectId)){
            synchronized (zsAllWarReportMap){
                if(!zsAllWarReportMap.containsKey(projectId)){
                    zsAllWarReportMap.put(projectId, new ArrayList<>());
                }
            }
        }
        List<ZsWarReport> list = zsAllWarReportMap.get(projectId);
        if(list == null){
            return;
        }
        synchronized (list) {
            list.add(report);
        }
    }

    //添加奖励
    private static void addProjectReward(ZsProjectReward reward){
        synchronized (UserLockerMgr.getUserLocker(reward.getUserId())){
            if(!zsAllRewardMap.containsKey(reward.getUserId())){
                zsAllRewardMap.put(reward.getUserId(), new ArrayList<>());
            }
            zsAllRewardMap.get(reward.getUserId()).add(reward);
        }
    }

    //承包项目
    public static int openProject(long playerId,long serverId, int num, UserBaseInfo userBaseInfo, int templateId, ZsProject myProject, ZsProjectOpenResult result) {

        //可开启限制
        List<ZsProject> myOpenProjectList = getUserOpenProject(serverId, playerId, eProjectStateType.InProgress.getIntValue());
        if (myOpenProjectList.size() >= result.getOpenNumLimit()) {
            return GameErrorCode.E_ZS_PROJECT_OPEN_TIMES_NO_ENOUGH;
        }

        ZsProjectInfo projectInfo = ZsConfigMgr.getZsProjectInfoMap().get(templateId);
        if(projectInfo == null){
            return GameErrorCode.E_ZS_PROJECT_CONFIG_NOT_FOUND;
        }

        //新增项目
        myProject.setBaseReward(projectInfo.getRewards());
        myProject.setDuration(projectInfo.getTime() * num);
        myProject.setOpenTime(DateHelper.getCurrentSecond());
        myProject.setOpenUser(userBaseInfo);
        myProject.setOpenUserId(playerId);
        myProject.setTemplateId(projectInfo.getId());
        myProject.setProjectId(globalProjectId.incrementAndGet());
        myProject.setServerId(serverId);
        myProject.setStateVal(eProjectStateType.InProgress.getIntValue());
        setExpectProfit(myProject);
        myProject.setInsertOption();
        myProject.getAdditionData().setProjectId(myProject.getProjectId());
        myProject.getAdditionData().setOpenTime(myProject.getOpenTime());

        //立项公告
        ZsProjectNotice notice = new ZsProjectNotice(myProject.getProjectId(), eProjectNoticeType.Open.getIntValue(), myProject.getOpenTime());
        ZsProjectNoticeParam param = getZsProjectNoticeParam(playerId, serverId, userBaseInfo);
        notice.addParamList(param);
        notice.setInsertOption();
        result.setNotice(notice);   //返回公告

        addZsProject(myProject);
        return 0;
    }

    /**
     * 是否结束前多久被劫(是否有冷却时间)
     * @param lastUpdateTime
     */
    public static boolean inCloseTimeOfEndBeRob(long lastUpdateTime){
        //int beginHour = ConfigMgr.getZsProjectOpenTime().get(2);
        int endHour = ConfigMgr.getZsProjectOpenTime().get(3);
        int hour = DateHelper.getHours();
        if(hour >= endHour){
            return false;
        }
        Calendar robedCalendar = Calendar.getInstance();
        robedCalendar.setTimeInMillis(lastUpdateTime);

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.set(Calendar.HOUR_OF_DAY, endHour);
        endCalendar.set(Calendar.MINUTE, 0);
        endCalendar.set(Calendar.SECOND, 0);
        endCalendar.set(Calendar.MILLISECOND, 0);

//        Calendar beginCalendar = Calendar.getInstance();
//        endCalendar.set(Calendar.HOUR_OF_DAY, beginHour);
//        endCalendar.set(Calendar.MINUTE, 0);
//        endCalendar.set(Calendar.SECOND, 0);
//        endCalendar.set(Calendar.MILLISECOND, 0);

        if(robedCalendar.getTimeInMillis() >= endCalendar.getTimeInMillis() - DateHelper.MINUTE_MILLIONS * GameConfig.ZHAOSHANG_END_TIME_NO_LIMIT){
            return true;
        }
        return false;
    }

    //项目席位抢占
    public static void robProjectSeat(long playerId, long playerServerId, long projectId, int seatId, long seatUserId, UserBaseInfo userBaseInfo, int templateId, ZsProjectSeatRobResult result) {
        ZsProject zsProject;
        if(result.getProjectServerId() > 0){
            zsProject = ZsMgr.getZsProjectByServerIdAndId(result.getProjectServerId(), projectId);
        }else {
            zsProject = ZsMgr.getZsProjectById(projectId);
        }
        if(zsProject == null){
            result.setRet(GameErrorCode.E_ZS_PROJECT_NOT_FOUND);    //找不到项目
            return;
        }
        ZsProjectInfo zsProjectInfo = ZsConfigMgr.getZsProjectInfoMap().get(templateId);
        if(zsProjectInfo == null){
            result.setRet(GameErrorCode.E_ZS_PROJECT_CONFIG_NOT_FOUND);
            return;
        }

        //自己的项目不能参与
        if(zsProject.getOpenUserId() == playerId && playerServerId == zsProject.getServerId()){
            result.setRet(GameErrorCode.E_ZS_PROJECT_CAN_NOT_ROB_SELF);
            return;
        }

        if(zsUserCoolDownMap.containsKey(playerId)){
            ZsUserCoolDown zsUserCoolDown = zsUserCoolDownMap.get(playerId);
            //被踢时间在免冷却CD周期内，且当前是免冷却CD周期，则不限制
            if(!inCloseTimeOfEndBeRob(zsUserCoolDown.getLastUpdateTime())) {

                //正常走冷却CD
                if (System.currentTimeMillis() - zsUserCoolDown.getLastUpdateTime() < result.getCoolDownLimit() * DateHelper.MINUTE_MILLIONS) {
                    result.setRet(GameErrorCode.E_ZS_PROJECT_SEAT_COOL_DOWN_LIMIT);
                    result.setLastRobTime(zsUserCoolDown.getLastUpdateTime());
                    return;
                }
            }
        }

        //请求的席位超出范围
        if(seatId < 1 || seatId > zsProjectInfo.getSeatNum()-1){
            result.setRet(GameErrorCode.E_ZS_PROJECT_SEAT_OUT_OF_RANGE);
            return;
        }

        //不允许跳空
        if(seatId - 1 > zsProject.getSeatMap().size()){
            result.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return;
        }

        int group1 = getGroupId(zsProject.getOpenUser().getServerId());
        int group2 = getGroupId(userBaseInfo.getServerId());
        if(group1 != group2){
            result.setRet(GameErrorCode.E_ZS_PROJECT_HAD_END);
            return;
        }

        //战报
        ZsWarReport report = null;
        //奖励
        ZsProjectNotice notice = null;

        synchronized (zsProject){
            int projectState = calZsProjectStateVal(zsProject);
            //项目已收官
            if(projectState == eProjectStateType.End.getIntValue()){
                result.setRet(GameErrorCode.E_ZS_PROJECT_HAD_END);
                return;
            }
            //不可参与同一个项目多次
            for (Map.Entry<Integer, ZsProjectSeat> seatEntry : zsProject.getSeatMap().entrySet()) {
                if(seatEntry.getValue().getUserId() == playerId){
                    result.setRet(GameErrorCode.E_ZS_PROJECT_HAD_JOIN_SAME_PROJECT);
                    return;
                }
            }
            synchronized (UserLockerMgr.getUserLocker(playerId)) {
                //参与项目数上限
                List<ZsProject> zsProjectList = getUserJoinProject(playerServerId, playerId, eProjectStateType.InProgress.getIntValue());
                if (zsProjectList.size() >= result.getRobNumLimit()) {
                    result.setRet(GameErrorCode.E_ZS_PROJECT_JOIN_TIME_REACH_LIMIT);
                    return;
                }
                ZsProjectSeat zsProjectSeat = zsProject.getSeatMap().get(seatId);
                //抢占pk
                if (zsProjectSeat != null) {
                    //项目席位数据已过时
                    if (seatUserId != zsProjectSeat.getUserId()) {
                        result.setRet(GameErrorCode.E_ZS_PROJECT_SEAT_INFO_OUT_TIME);
                        return;
                    }
                    //不能pk自己
                    if (playerId == zsProjectSeat.getUserId() && playerServerId == zsProjectSeat.getServerId()) {
                        result.setRet(GameErrorCode.E_ZS_PROJECT_SEAT_IS_YOURSELF);
                        return;
                    }
                    //是否在受保护周期
                    if (System.currentTimeMillis() - zsProjectSeat.getSitTime() <= GameConfig.ZHAOSHANG_PROTECT_LIMIT * DateHelper.MINUTE_MILLIONS) {
                        result.setRet(GameErrorCode.E_ZS_ROB_USER_IN_PROTECT_TIME);
                        return;
                    }
                    robPk(userBaseInfo, zsProject.getSeatUserMap().get(seatId), zsProjectSeat, result);
                    result.setEnemyInfo(zsProject.getSeatUserMap().get(seatId));
                    sendRobSuccessToServer(playerServerId, playerId, seatUserId, result.getResultType() == eProjectSeatRobResultType.RobSuccess.getIntValue());
                    //pk胜利
                    if (result.getResultType() == eProjectSeatRobResultType.RobSuccess.getIntValue()) {
                        //给对方结算，有被驱战报
                        report = new ZsWarReport();
                        calPlayerReward(zsProject, zsProjectSeat, report);
                        setDefendFailReport(playerId, seatId, seatUserId, userBaseInfo, zsProject, report, zsProjectSeat);

                        //驱逐公告
                        notice = new ZsProjectNotice(zsProject.getProjectId(), eProjectNoticeType.Rob.getIntValue(), report.getAddTime());
                        ZsProjectNoticeParam param = getZsProjectNoticeParam(playerId, playerServerId, userBaseInfo);
                        notice.addParamList(param);

                        param = new ZsProjectNoticeParam();
                        param.setServerId(zsProjectSeat.getServerId());
                        param.setUserId(zsProjectSeat.getUserId());
                        param.setTitleId(report.getUserBaseInfo().getTitleId());
                        param.setCity((userBaseInfo.getHideVipAndAddress() & HideVipAddressMark.HIDE_ADDRESS) > 0 ? "" : report.getUserBaseInfo().getCity());
                        param.setNickName(report.getUserBaseInfo().getNickName());
                        notice.addParamList(param);
                        notice.setInsertOption();

                        //坐下
                        sitSuccess(playerId, playerServerId, seatId, userBaseInfo, result, zsProject);

                        //给对方冷却时间
                        ZsUserCoolDown zsUserCoolDown = zsUserCoolDownMap.get(seatUserId);
                        if (zsUserCoolDown == null) {
                            zsUserCoolDown = new ZsUserCoolDown();
                            zsUserCoolDown.setUserId(seatUserId);
                            zsUserCoolDown.setServerId(zsProjectSeat.getServerId());
                            zsUserCoolDown.setLastUpdateTime(System.currentTimeMillis());
                            zsUserCoolDown.setInsertOption();
                            zsUserCoolDownMap.put(seatUserId, zsUserCoolDown);
                        } else {
                            zsUserCoolDown.setLastUpdateTime(System.currentTimeMillis());
                        }
                        sendPlayerProjectStateInfo(report.getUserBaseInfo().getServerId(), zsProjectSeat.getUserId());
                        sendPlayerProjectStateInfo(playerServerId, playerId);
                    } else {
                        ZsWarReport lastReport = findWinWarReport(projectId, zsProjectSeat.getUserId(), zsProjectSeat.getId(), playerId);
                        if (lastReport != null) {
                            if (System.currentTimeMillis() - lastReport.getSitTime() < 5 * 60 * 1000) {
                                return;   //5分钟内不生成相同的战报
                            }
                        }
                        //给对方防守胜利的战报
                        report = new ZsWarReport();
                        setDefendWinReport(playerId, seatId, seatUserId, userBaseInfo, zsProject, report, zsProjectSeat);
                    }
                } else {
                    if (seatUserId != 0) {
                        result.setRet(GameErrorCode.E_ZS_PROJECT_SEAT_INFO_OUT_TIME);     //项目席位数据已过时（客户端传错数据）
                        return;
                    }

                    result.setResultType(eProjectSeatRobResultType.JoinSuccess.getIntValue());

                    //入座公告
                    notice = new ZsProjectNotice(zsProject.getProjectId(), eProjectNoticeType.Join.getIntValue(), DateHelper.getCurrentSecond());
                    ZsProjectNoticeParam param = getZsProjectNoticeParam(playerId, playerServerId, userBaseInfo);
                    notice.addParamList(param);
                    notice.setInsertOption();

                    //加入
                    sitSuccess(playerId, playerServerId, seatId, userBaseInfo, result, zsProject);

                    sendPlayerProjectStateInfo(playerServerId, playerId);
                }

                sendJoinSuccessToServer(playerServerId, playerId, projectId, zsProject.getTemplateId(), zsProject.getOpenUserId(), seatId, result.getDecorationClass());
            }
        }

        if(report != null){
            addWarReport(zsProject.getProjectId(), report);
            //有奖励
            if(report.getType() != eZsReportType.Win.getIntValue()) {
                ZsProjectReward reward = copyToZsProjectReward(report);
                reward.setInsertOption();
                addProjectReward(reward);
            }
            //战报下发区服
            sendWarReportAddToGameServer(report.getServerId(), report.getUserId(), report);
        }
        if(notice != null){
            addProjectNotice(notice.getProjectId(), notice);
        }
    }

    private static ZsProjectNoticeParam getZsProjectNoticeParam(long playerId, long playerServerId, UserBaseInfo userBaseInfo) {
        ZsProjectNoticeParam param = new ZsProjectNoticeParam();
        param.setUserId(playerId);
        param.setServerId(playerServerId);
        param.setTitleId(userBaseInfo.getTitleId());
        param.setCity((userBaseInfo.getHideVipAndAddress() & HideVipAddressMark.HIDE_ADDRESS) > 0 ? "" : userBaseInfo.getCity());
        param.setNickName(userBaseInfo.getNickName());
        return param;
    }

    private static void setDefendWinReport(long playerId, int seatId, long seatUserId, UserBaseInfo userBaseInfo, ZsProject zsProject, ZsWarReport report, ZsProjectSeat zsProjectSeat) {
        report.setAddTime(DateHelper.getCurrentSecond());
        report.setSitTime(DateHelper.getCurrentTime());//防守胜利，被抢座位时间（补）
        report.setEnemyUserId(playerId);
        report.setEnemyBaseInfo(userBaseInfo);
        report.setProjectId(zsProject.getProjectId());
        report.setSeatId(seatId);
        report.setUserId(seatUserId);
        report.setUserBaseInfo(zsProject.getSeatUserMap().get(seatId));
        report.setServerId(zsProjectSeat.getServerId());
        report.setTemplateId(zsProject.getTemplateId());
        report.setType(eZsReportType.Win.getIntValue());
        report.setDecorationOver(isDecorationOverTime(zsProjectSeat.getDecorationOverTime()));
        report.setOpenUserId(zsProject.getOpenUserId());
        report.setOpenDecoration(zsProject.getOpenUser().getDecoration());
        report.setOpenTitleId(zsProject.getOpenUser().getTitleId());
        report.setInsertOption();
    }

    private static void setDefendFailReport(long playerId, int seatId, long seatUserId, UserBaseInfo userBaseInfo, ZsProject zsProject, ZsWarReport report, ZsProjectSeat zsProjectSeat) {
        report.setAddTime(DateHelper.getCurrentSecond());
        report.setSitTime(zsProjectSeat.getSitTime());
        report.setEnemyUserId(playerId);
        report.setEnemyBaseInfo(userBaseInfo);
        report.setProjectId(zsProject.getProjectId());
        report.setSeatId(seatId);
        report.setTemplateId(zsProject.getTemplateId());
        report.setType(eZsReportType.Fail.getIntValue());
        report.setUserId(seatUserId);
        report.setUserBaseInfo(zsProject.getSeatUserMap().get(seatId));
        report.setServerId(zsProjectSeat.getServerId());
        report.setDecorationOver(isDecorationOverTime(zsProjectSeat.getDecorationOverTime()));
        report.setOpenUserId(zsProject.getOpenUserId());
        report.setOpenDecoration(zsProject.getOpenUser().getDecoration());
        report.setOpenTitleId(zsProject.getOpenUser().getTitleId());
        report.setInsertOption();
    }

    private static void sendRobSuccessToServer(long playerServerId, long playerId, long seatUserId,boolean success) {
        ZhaoShangProto.ZsRobToServerMsg.Builder msg = ZhaoShangProto.ZsRobToServerMsg.newBuilder();
        msg.setRobUserId(seatUserId);
        msg.setSuccess(success);
        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_ZS_ROB_FROM_CROSS, msg);
        MessageHelper.sendPacket(playerServerId,playerId,message);
    }

    private static void sendJoinSuccessToServer(long playerServerId, long playerId, long projectId, int templateId, long openUserId, int seatId, int decorationClass) {
        ZhaoShangProto.ZsJoinToServerMsg.Builder msg = ZhaoShangProto.ZsJoinToServerMsg.newBuilder();
        msg.setSeatId(seatId);
        msg.setProjectId(projectId);
        msg.setTemplateId(templateId);
        msg.setOpenUserId(openUserId);
        msg.setDecorationClass(decorationClass);
        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_ZS_SIT_DOWN_FROM_CROSS, msg);
        MessageHelper.sendPacket(playerServerId,playerId,message);
    }

    //推送战报给区服
    private static void sendWarReportAddToGameServer(long serverId, long userId, ZsWarReport report) {
        ZhaoShangProto.ZsWarReportAddFromCross.Builder addMsg = ZhaoShangProto.ZsWarReportAddFromCross.newBuilder();
        ZhaoShangProto.ZsWarReportInfoTemp.Builder builder = ZhaoShangPb.parseToZsWarReportTemp(report);
        addMsg.setWarReportInfo(builder);
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.S_ZS_WAR_REPORT_ADD_FROM_CROSS, addMsg));
    }

    //计算玩家奖励（被驱逐）
    private static Property calPlayerReward(ZsProject zsProject, ZsProjectSeat zsProjectSeat, ZsWarReport report) {
        Property property = new Property();
        long sitMinute = (DateHelper.getCurrentTime() - zsProjectSeat.getSitTime()) / (60 * 1000);
        Property baseReward = PropertyHelper.parseStringToProperty(zsProject.getBaseReward());
        if(sitMinute >= 1){  //大于1分钟有礼
            //if(zsProjectSeat.getDecorationOverTime() != 0 && DateHelper.getCurrentSecond() > zsProjectSeat.getDecorationOverTime()){
            //    calPlayerReward(zsProject, 0, property, sitMinute, baseReward);
            //}else {
                calPlayerReward(zsProject, zsProject.getAddition(), property, sitMinute, baseReward);
            //}
        }
        if(report != null){
            report.setDuration((int)sitMinute);
            report.setReward(PropertyHelper.parsePropertyToString(property));
        }
        return property;
    }

    //加成计算
    private static void calPlayerReward(ZsProject zsProject, int decorationAddition, Property reward, long sitMinute, Property baseReward) {
        int titleAddition = zsProject.getTitleAddition() < 1000 ? 1000 : zsProject.getTitleAddition();
        int curioAddition = 0;
        if(zsProject.getAdditionData() != null){
            curioAddition = zsProject.getAdditionData().getCurioAddition();
        }
        for (int goodId : baseReward.getGoods().keySet()) {
            BigDecimal baseCount = BigDecimal.valueOf(baseReward.getCountByGoodsId(goodId).longValue());
            long num = baseCount.multiply(BigDecimal.valueOf((double)titleAddition / 1000))
                    .multiply(BigDecimal.valueOf((1 + ((double)decorationAddition / 1000))))
                    .multiply(BigDecimal.valueOf((1 + ((double)curioAddition / 1000))))
                    .setScale(0, BigDecimal.ROUND_UP).multiply(BigDecimal.valueOf(sitMinute)).setScale(0, BigDecimal.ROUND_UP).longValue();
            reward.addProperty(goodId, BigInteger.valueOf(num));
        }
    }

    //计算项目收益（每分钟收益=基础收益*身份加成）
    public static void setExpectProfit(ZsProject zsProject){
        List<Integer> rewardList = StringUtils.stringToIntegerList(zsProject.getBaseReward(), "=");
        int titleAddition = zsProject.getTitleAddition() < 1000 ? 1000 : zsProject.getTitleAddition();
        int curioAddition = 0;
        if(zsProject.getAdditionData() != null){
            curioAddition = zsProject.getAdditionData().getCurioAddition();
        }
        BigDecimal expectProfit = BigDecimal.valueOf(rewardList.get(1)).multiply(BigDecimal.valueOf((1 + ((double) zsProject.getAddition() / 1000) + (double)curioAddition / 1000)))
                .multiply(BigDecimal.valueOf((double)titleAddition / 1000)).setScale(0, BigDecimal.ROUND_UP);
        zsProject.setExpectProfit(expectProfit.longValue());
    }

    //占位成功
    private static void sitSuccess(long playerId, long playerServerId, int seatId, UserBaseInfo userBaseInfo, ZsProjectSeatRobResult result, ZsProject zsProject) {
        ZsProjectSeat newZsProjectSeat = new ZsProjectSeat();
        newZsProjectSeat.setId(seatId);
        newZsProjectSeat.setServerId(playerServerId);
        newZsProjectSeat.setUserId(playerId);
        newZsProjectSeat.setSitTime(DateHelper.getCurrentTime());
        newZsProjectSeat.setAddition(result.getAddition());
        newZsProjectSeat.setDecorationClass(result.getDecorationClass());
        newZsProjectSeat.setDecorationOverTime(result.getDecorationOverTime());
        zsProject.setSeatUser(seatId, userBaseInfo);
        zsProject.setSeat(seatId, newZsProjectSeat);
        result.setZsProject(zsProject);
    }

    //玩家实力比拼
    private static void robPk(UserBaseInfo challenger, UserBaseInfo seatOwner, ZsProjectSeat zsProjectSeat, ZsProjectSeatRobResult result) {
        int seatDecorationClass = zsProjectSeat.getDecorationClass();
        if(isDecorationOverTime(zsProjectSeat.getDecorationOverTime())){
            seatDecorationClass = -1;  //称号过期无阶级
        }
        if(result.getDecorationClass() > seatDecorationClass){  //胜
            result.setPkRounds(1);  //第一轮
            result.setResultType(eProjectSeatRobResultType.RobSuccess.getIntValue());
            return;
        }
        if(result.getDecorationClass() < seatDecorationClass){  //败
            result.setPkRounds(1);  //第一轮
            result.setResultType(eProjectSeatRobResultType.RobFail.getIntValue());
            return;
        }
        if(challenger.getTitleId() > seatOwner.getTitleId()){ //胜
            result.setPkRounds(2);  //第二轮
            result.setResultType(eProjectSeatRobResultType.RobSuccess.getIntValue());
            return;
        }
        if(challenger.getTitleId() < seatOwner.getTitleId()){//败
            result.setPkRounds(2);  //第二轮
            result.setResultType(eProjectSeatRobResultType.RobFail.getIntValue());
            return;
        }
        long challengerPrestige = challenger.getPrestige();
        long seatOwnerPrestige = seatOwner.getPrestige();
        if(challengerPrestige > seatOwnerPrestige){
            result.setPkRounds(3);  //第三轮
            result.setResultType(eProjectSeatRobResultType.RobSuccess.getIntValue());
            return;
        }
        result.setPkRounds(3);  //第三轮
        result.setResultType(eProjectSeatRobResultType.RobFail.getIntValue());
        return;
    }

    private static boolean isDecorationOverTime(long decorationOverTime) {
        return decorationOverTime != 0 && DateHelper.getCurrentSecond() > decorationOverTime;
    }

    //检测项目状态
    public static void checkAllProjectState() {
        long startTimeMillis = System.currentTimeMillis();
        for(Map.Entry<Long, Map<Long, ZsProject>>  serverProjectDataEntry : zsAllProjectMap.entrySet()) {  //遍历区服
            long serverId = serverProjectDataEntry.getKey();
            Map<Long, ZsProject> projectMap = serverProjectDataEntry.getValue();
            for(long projectId : projectMap.keySet()) {
                ZsProject zsProject = projectMap.get(projectId);
                if (zsProject == null) {
                    continue;
                }
                List<ZsProjectReward> rewardList = null;
                synchronized (zsProject) {
                    if (zsProject.isSendReward()) {
                        continue;
                    }
                    if (zsProject.getStateVal() == eProjectStateType.End.getIntValue()) {
                        //收官，奖励
                        rewardList = doProjectFinishReward(zsProject);
                    } else {
                        int preState = zsProject.getStateVal();
                        int nowState = calZsProjectStateVal(zsProject);
                        //正常收官
                        if (preState != nowState && nowState == eProjectStateType.End.getIntValue()) {
                            zsProject.setStateVal(eProjectStateType.End.getIntValue());
                            zsProject.setFinishType(eZsProjectFinishType.Normal.getIntValue());

                            sendPlayerProjectStateInfo(zsProject.getServerId(), zsProject.getOpenUserId());
                            //遍历座位，推送参与个数
                            for (int seatId : zsProject.getSeatMap().keySet()) {
                                ZsProjectSeat seat = zsProject.getSeatMap().get(seatId);
                                sendPlayerProjectStateInfo(seat.getServerId(), seat.getUserId());
                            }
                            //收官，奖励
                            rewardList = doProjectFinishReward(zsProject);

                        } else {
                            Set<Long> seatServerSet = new HashSet<>();
                            //遍历座位
                            for (int seatId : zsProject.getSeatMap().keySet()) {
                                seatServerSet.add(zsProject.getSeatMap().get(seatId).getServerId());
                            }
                            //检测区服是否变更（遍历座位的方式解决每次变更的分组id可不变，符合实际运维情况)
                            //但视占位区服的分布情况可能,存在未被结算的项目正确保留到新区服范围-此情况影响微小）
                            if (serverGroupChange(serverId, seatServerSet)) {
                                zsProject.setStateVal(eProjectStateType.End.getIntValue());
                                zsProject.setFinishType(eZsProjectFinishType.GroupChange.getIntValue());
                                sendPlayerProjectStateInfo(zsProject.getServerId(), zsProject.getOpenUserId());
                            }
                        }
                    }
                }
                if (rewardList != null) {
                    for (ZsProjectReward zsProjectReward : rewardList) {
                        addProjectReward(zsProjectReward);
                        //红点
                        syncRedDot(zsProjectReward.getServerId(), zsProjectReward.getUserId());
                    }
                }
            }
        }
        logger.info("cal all zs project state cost {}", DateHelper.getCurrentTime() - startTimeMillis);
    }

    //项目结算
    private static List<ZsProjectReward> doProjectFinishReward(ZsProject zsProject) {
        Property baseReward = PropertyHelper.parseStringToProperty(zsProject.getBaseReward());
        Property openUserReward = new Property();
        int currentSecond = DateHelper.getCurrentSecond();
        //if(zsProject.getDecorationOverTime() != 0 && currentSecond > zsProject.getDecorationOverTime()){
        //    calPlayerReward(zsProject, 0, openUserReward, zsProject.getDuration(), baseReward);
        //}else {
            calPlayerReward(zsProject, zsProject.getAddition(), openUserReward, zsProject.getDuration(), baseReward);
        //}
        //立项人奖励
        List<ZsProjectReward> rewardList = new ArrayList<>();
        ZsProjectReward reward = new ZsProjectReward();
        reward.setUserId(zsProject.getOpenUserId());
        reward.setUserBaseInfo(zsProject.getOpenUser());
        reward.setServerId(zsProject.getServerId());
        reward.setType(eZsReportType.Complete.getIntValue());
        reward.setAddTime(currentSecond);
        reward.setSitTime((long)zsProject.getOpenTime() * 1000);
        reward.setProjectId(zsProject.getProjectId());
        reward.setSeatId(0);
        reward.setTemplateId(zsProject.getTemplateId());
        reward.setReward(PropertyHelper.parsePropertyToString(openUserReward));
        reward.setDuration(zsProject.getDuration());
        reward.setInsertOption();
        rewardList.add(reward);
        Set<Long> serverIdSet = new HashSet<>();
        serverIdSet.add(zsProject.getServerId());
        ZhaoShangProto.CrossZsProjectFinishSyncMsg.Builder crossRespMsg = ZhaoShangProto.CrossZsProjectFinishSyncMsg.newBuilder();
        ZhaoShangProto.CrossZsProjectFinishSeatUserTemp.Builder userTemp = ZhaoShangProto.CrossZsProjectFinishSeatUserTemp.newBuilder();
        userTemp.setUserId(zsProject.getOpenUserId());
        userTemp.setServerId(zsProject.getServerId());
        crossRespMsg.addUser(userTemp);
        //席位奖励
        int endTime = (zsProject.getOpenTime() + zsProject.getDuration() * 60) / 60;   //分钟
        for(ZsProjectSeat projectSeat : zsProject.getSeatMap().values()){
            long duration =  endTime - (projectSeat.getSitTime() / (1000 * 60));   //占位时长
            Property seatReward = new Property();
            //if(projectSeat.getDecorationOverTime() != 0 && currentSecond > projectSeat.getDecorationOverTime()){
            //    calPlayerReward(zsProject, 0, seatReward, duration, baseReward);
            //}else {
                calPlayerReward(zsProject, zsProject.getAddition(), seatReward, duration, baseReward);
            //}
            reward = new ZsProjectReward();
            reward.setUserId(projectSeat.getUserId());
            reward.setUserBaseInfo(zsProject.getSeatUserMap().get(projectSeat.getId()));
            reward.setServerId(projectSeat.getServerId());
            reward.setType(eZsReportType.Complete.getIntValue());
            reward.setAddTime(currentSecond);
            reward.setSitTime(projectSeat.getSitTime());
            reward.setProjectId(zsProject.getProjectId());
            reward.setSeatId(projectSeat.getId());
            reward.setTemplateId(zsProject.getTemplateId());
            reward.setReward(PropertyHelper.parsePropertyToString(seatReward));
            reward.setDuration((int)duration);
            reward.setInsertOption();
            rewardList.add(reward);
            projectSeat.setSendReward(true);
            serverIdSet.add(projectSeat.getServerId());
            ZhaoShangProto.CrossZsProjectFinishSeatUserTemp.Builder seatUserTemp = ZhaoShangProto.CrossZsProjectFinishSeatUserTemp.newBuilder();
            seatUserTemp.setUserId(projectSeat.getUserId());
            seatUserTemp.setServerId(projectSeat.getServerId());
            crossRespMsg.addUser(seatUserTemp);
        }
        zsProject.setSendReward(true);
        crossRespMsg.setTemplateId(zsProject.getTemplateId());
        YanQuMessage message = YanQuMessageUtils.buildMessage(Protocol.S_ZS_PROJECT_FINISH_NOTICE, crossRespMsg);
        for (Long serverId : serverIdSet) {
            MessageHelper.sendPacket(serverId, 0, message);
        }
        return rewardList;
    }

    //玩家信息变更，更新项目信息
    public static void syncUserBaseInfo(long serverId, UserBaseInfo userBaseInfo, long uerId, ZsAdditionInfos additionInfos) {
        List<Long> serverList = getGroupServer(serverId);
        List<ZsProject> projectList = new ArrayList<>();
        for (Long sid : serverList) {
            Map<Long, ZsProject> projectMap = zsAllProjectMap.get(sid);
            if (projectMap != null) {
                projectList.addAll(projectMap.values());
            }
        }
        for (ZsProject zsProject : projectList) {
            int state = calZsProjectStateVal(zsProject);
            if(state == eProjectStateType.End.getIntValue()){
                continue;
            }
            if (zsProject.getOpenUserId() == uerId && zsProject.getServerId() == serverId) {
                //zsProject.setOpenUser(userBaseInfo);
                //zsProject.setTitleAddition(additionInfos.getTitleAddition());
                //zsProject.setAddition(additionInfos.getDecorationAddition());
                //zsProject.setDecorationOverTime(additionInfos.getDecorationOverTime());
                //setExpectProfit(zsProject);
                continue;
            }
            synchronized (zsProject) {
                for(int seatId : zsProject.getSeatMap().keySet()){
                    ZsProjectSeat zsProjectSeat = zsProject.getSeatMap().get(seatId);
                    if(zsProjectSeat.getUserId() == uerId && zsProjectSeat.getServerId() == serverId){
                        zsProject.setSeatUser(seatId, userBaseInfo);
                        zsProjectSeat.setAddition(additionInfos.getDecorationAddition());
                        zsProjectSeat.setDecorationClass(additionInfos.getDecorationClass());
                        zsProjectSeat.setDecorationOverTime(additionInfos.getDecorationOverTime());
                    }
                }
            }
        }
    }

    //同步玩家战报回区服
    public static List<ZsWarReport> getAndUpdateZsWarReportList(long serverId, long playerId) {
        List<ZsWarReport> resultList = new ArrayList<>();
        for(long key : zsAllWarReportMap.keySet()) {
            List<ZsWarReport> zsWarReportList = zsAllWarReportMap.get(key);
            if(zsWarReportList == null){
                continue;
            }
            int size = zsWarReportList.size();
            for(int i = 0; i < size; i++){
                ZsWarReport zsWarReport = zsWarReportList.get(i);
                if(zsWarReport.isSync() || zsWarReport.isDirty()){
                    continue;
                }
                if(zsWarReport.getServerId() == serverId && zsWarReport.getUserId() == playerId){
                    resultList.add(zsWarReport);
                    zsWarReport.setSync(true);
                }
            }
        }
        return resultList;
    }

    //过期数据移除
    public static void removeOutTimeData(){
        int curSeconds = DateHelper.getCurrentSecond();
        List<Long> removedProjectIdList = new ArrayList<>();
        //移除项目
        for(long serverId : zsAllProjectMap.keySet()){
            Map<Long, ZsProject> zsProjectMap = zsAllProjectMap.get(serverId);
            for(Map.Entry<Long, ZsProject> dataEntry : zsProjectMap.entrySet()){
                ZsProject zsProject = dataEntry.getValue();
                if(zsProject.getStateVal() == eProjectStateType.End.getIntValue() && zsProject.isSendReward() && !zsProject.isDirty()
                        && (curSeconds - zsProject.getOpenTime() > keepDataDays * DateHelper.DAY_SECONDS)){
                    zsAllProjectMap.get(serverId).remove(dataEntry.getKey(), dataEntry.getValue());
                    removedProjectIdList.add(zsProject.getProjectId());
                }
            }
        }

        //移除奖励
        int endTime = (int)((System.currentTimeMillis() - DateHelper.DAY_MILLIONS * 30) / 1000);
        for(long userId : zsAllRewardMap.keySet()){
            List<ZsProjectReward> list = zsAllRewardMap.get(userId);
            synchronized (UserLockerMgr.getUserLocker(userId)){
                Iterator<ZsProjectReward> iterator = list.iterator();
                while (iterator.hasNext()){
                    ZsProjectReward reward = iterator.next();
                    if(reward.getAddTime() <= endTime || (reward.isSendReward() && !reward.isDirty())){
                        iterator.remove();
                    }
                }
            }
        }

        //移除项目公告
        //移除战报
        for (long projectId : removedProjectIdList) {
            zsAllProjectNoticeMap.remove(projectId);
            zsAllWarReportMap.remove(projectId);
        }

    }

    //下发玩家参与项目的信息
    public static void sendPlayerProjectStateInfo(long serverId, long playerId) {
        try {
            List<ZsProject> zsProjectList = getUserOpenProject(serverId, playerId, eProjectStateType.InProgress.getIntValue());
            List<ZsProject> zsProjectList2 = getUserJoinProject(serverId, playerId, eProjectStateType.InProgress.getIntValue());
            ZhaoShangProto.ZsPlayerProjectStateInfoSyncMsg.Builder syncMsg = ZhaoShangProto.ZsPlayerProjectStateInfoSyncMsg.newBuilder();
            syncMsg.setOpenNum(zsProjectList.size());
            syncMsg.setJoinNum(zsProjectList2.size());
            ZsUserCoolDown userCoolDown = ZsMgr.getZsUserCoolDownMap().get(playerId);
            if(userCoolDown != null){
                syncMsg.setLastRobbedTime((int)(userCoolDown.getLastUpdateTime() / 1000));
            }
            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_ZS_USER_PROJECT_INFO_SYNC, syncMsg));
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
    }

    public static ZsProjectReward copyToZsProjectReward(ZsWarReport report){
        ZsProjectReward data = new ZsProjectReward();
        data.setAddTime(report.getAddTime());
        data.setDuration(report.getDuration());
        data.setEnemyBaseInfo(report.getEnemyBaseInfo());
        data.setEnemyUserId(report.getEnemyUserId());
        data.setProjectId(report.getProjectId());
        data.setReward(report.getReward());
        data.setSeatId(report.getSeatId());
        //data.setSendReward(report.isSendReward());  状态不传递
        data.setServerId(report.getServerId());
        data.setSitTime(report.getSitTime());
        data.setTemplateId(report.getTemplateId());
        data.setType(report.getType());
        data.setUserBaseInfo(report.getUserBaseInfo());
        data.setUserId(report.getUserId());
        return data;
    }

    //下发红点，服务端负责项目收官、被驱逐情况（战报、奖励）
    public static void syncRedDot(long serverId, long playerId){
        //logger.info("cross2 syncRedDot {},{}", serverId, playerId);
        boolean sendRedHot = false;
        if(zsAllRewardMap.containsKey(playerId)) {
            List<ZsProjectReward> rewards = zsAllRewardMap.get(playerId);
            synchronized (UserLockerMgr.getUserLocker(playerId)) {
                for (ZsProjectReward zsProjectReward : rewards) {
                    if (!zsProjectReward.isSendReward()) {
                        sendRedHot = true;
                        break;
                    }
                }
            }
        }
        if(sendRedHot){
            WorldMessageProto.RedHotNotifyMsg.Builder redHotMsg = WorldMessageProto.RedHotNotifyMsg.newBuilder();
            redHotMsg.setType(eRedHotNotifyType.ZsWarReport.getValue());
            redHotMsg.setCount(1);
            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_RED_HOT_NOTIFY, redHotMsg));
        }
    }

    //领奖
    public static void getReward(long serverId, long playerId){
        //logger.info("cross2 getReward {},{}", serverId, playerId);
        List<ZsProjectReward> resultList = new ArrayList<>();
        if(zsAllRewardMap.containsKey(playerId)){
            List<ZsProjectReward> rewards = zsAllRewardMap.get(playerId);
            synchronized (UserLockerMgr.getUserLocker(playerId)){
                for(ZsProjectReward zsProjectReward : rewards){
                    if(!zsProjectReward.isSendReward()){
                        resultList.add(zsProjectReward);
                        zsProjectReward.setSendReward(true);
                    }
                }
            }
        }
        if(resultList.size() > 0){
            ZhaoShangProto.ZsWarReportListRespMsg.Builder respMsg = ZhaoShangProto.ZsWarReportListRespMsg.newBuilder();
            for(ZsProjectReward reward : resultList) {
                respMsg.addReportList(ZhaoShangPb.parseToZsWarReportTemp(reward));
            }
            respMsg.setRet(0);
            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.S_ZS_GET_REWARD_FROM_CROSS, respMsg));
            syncRedDot(serverId, playerId);
        }else {
            //logger.info("cross2 not reward {}---------  {}", serverId, playerId);
        }
    }

    public static void repair(long userId, String param){
        logger.info("repair {} {}", userId, param);


    }

}
